package com.bsoft.gol.hcb.service.guide;

import com.bsoft.gol.hcb.bean.guide.ClinicGuideCheckDTO;
import com.bsoft.gol.hcb.service.ClinicGuideService;
import com.bsoft.gol.hcb.utils.CommonUtils;
import com.bsoft.gol.mpi.model.Certificate;
import com.bsoft.gol.mpi.provider.IMPIProvider;
import com.bsoft.gol.mpi.service.MPIException;
import com.security.cipher.sm.SM4Utils;
import ctd.controller.exception.ControllerException;
import ctd.net.rpc.Client;
import ctd.spring.boot.annotation.SsdevReference;
import ctd.spring.boot.annotation.SsdevService;
import ctd.util.BeanUtils;
import ctd.util.annotation.RpcService;
import hcn.api.service.api.drug.DrugTaskingService;
import hcn.base.Organization;
import hcn.base.clinicguide.ClinicGuideCheckVO;
import hcn.base.clinicguide.ClinicGuideTipDTO;
import hcn.base.clinicguide.ClinicGuideTipVO;
import hcn.common.CodeDefinition;
import hcn.ods.OdsRegprepare;
import hcn.protocol.brandnew.dengji.menzhenyuyue.QueryUndeliveredDrugsXmlRequest;
import hcn.protocol.ods.RecordListBean;
import hcn.protocol.ods.hospitalQueue.HospitalFamilyQueueListResponse;
import hcn.protocol.ods.hospitalQueue.HospitalFamilyQueueListXmlRequest;
import hcn.protocol.ods.hospitalQueue.IdCard;
import hcn.protocol.ods.hospitalQueue.IdCardLists;
import hcn.protocol.registration.PatientIdentityVo;
import hcn.protocol.registration.PatientMedicalVo;
import hcn.protocol.registration.TakeNumberRequest;
import hcn.rep.request.*;
import hcn.rep.response.ExamAppointListAppResponse;
import hcn.rep.response.ExamAppointmentInfoResp;
import hcn.rep.response.GetCheckAppointmentItemResponse;
import hcn.response.PrescriptionList;
import hcn.response.bean.PatientMedicalCardInformation;
import hcn.service.event.registration.RegStatus;
import hcn.service.queue.qo.HospitalFamilyQueueListQo;
import hcn.service.queue.vo.HospitalFamilyQueueVo;
import hcn.util.BaseResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import service.rpc.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: lanyu
 * @Description: 就诊服务指南
 * @Date: create in 2022/8/11 16:34
 */
@SsdevService("clinicGuideService")
public class ClinicGuideServiceImpl implements ClinicGuideService {
    private static final Logger logger = LoggerFactory.getLogger(ClinicGuideServiceImpl.class);
    @SsdevReference("gol-mpi.mpiProvider")
    private IMPIProvider mpiProvider;
    @Autowired
    ICheckAppointmentService checkAppointmentService;

    @Autowired
    IExamineAppointmentService examineAppointmentService;

    @SsdevReference("hcnInterface.drugTaskingService")
    DrugTaskingService drugTaskingService;
    @Autowired
    OrganizationInfoIntf organizationInfoService;
    @Autowired
    IRegPrepareService regPrepareService;
    @Autowired
    IRegistrationTransformService registrationTransformService;
    @Autowired
    private INavigationListSettingsService navigationListSettingsService;

    public void setMpiProvider(IMPIProvider mpiProvider) {
        this.mpiProvider = mpiProvider;
    }

    /**
     * 患者待发药记录查询
     * @param xmlRequest
     * @return
     * @throws ControllerException
     */
    @Override
    @RpcService
    public List<PrescriptionList> queryDrugTakingList(QueryUndeliveredDrugsXmlRequest xmlRequest) throws ControllerException {
        List<PrescriptionList> takingList = new ArrayList<>();
        try {
            takingList = (List<PrescriptionList>) Client.rpcInvoke("hcnInterface.drugTaskingService", "queryDrugTakingList", xmlRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return takingList;
    }

    /**
     * 获取符合的检查检验列表数据
     *
     * @param dto
     * @return
     * @throws ControllerException
     */
    @RpcService
    @Override
    public ClinicGuideCheckVO getAllInspectionReport(ClinicGuideCheckDTO dto) throws ControllerException {
        ClinicGuideCheckVO vo = new ClinicGuideCheckVO();
        //查询检查列表
        vo.setCheckList(check(dto));
        //查询检验列表,未预约
        ExamAppointListAppResponse exam = exam(dto);
        if (CommonUtils.isNotEmpty(exam)) {
            vo.setInspectionList(exam.getExamLabRequestResps());
            vo.setPatient(exam.getPatient());
        }
        return vo;
    }

    @RpcService
    @Override
    public ClinicGuideTipVO getCheckTip(ClinicGuideTipDTO tipDto) throws ControllerException {
        ClinicGuideTipVO vo = new ClinicGuideTipVO();

        int checkNo = 0;
        ClinicGuideCheckDTO dto = new ClinicGuideCheckDTO();
        dto.setOrgCode(tipDto.getLocalOrgId());
        dto.setIdCardCode(tipDto.getIdCardCode());
        dto.setIdCard(tipDto.getIdCard());
        dto.setMedicalCardType(tipDto.getMedicalCardType());
        dto.setMedicalCardId(tipDto.getMedicalCardID());
        List<GetCheckAppointmentItemResponse> checkList = check(dto);
        if (CommonUtils.isNotEmpty(checkList)) {
            checkNo = checkNo + checkList.size();
        }
        ExamAppointListAppResponse exam = exam(dto);
        if (CommonUtils.isNotEmpty(exam) && CommonUtils.isNotEmpty(exam.getExamLabRequestResps())) {
            checkNo = checkNo + (exam.getExamLabRequestResps().size());
        }
        vo.setTip(checkNo);
        return vo;
    }

    @RpcService
    @Override
    public ClinicGuideTipVO drugTakingTip(ClinicGuideTipDTO tipDto) throws ControllerException {
        List<PrescriptionList> result = null;
        ClinicGuideTipVO vo = new ClinicGuideTipVO();
        try {
            QueryUndeliveredDrugsXmlRequest dto = new QueryUndeliveredDrugsXmlRequest();
            dto.setOrganizationId(tipDto.getLocalOrgId());
            //查全部
            dto.setPrescriptionState("0");
            if (StringUtils.hasText(tipDto.getIdCard()) && StringUtils.hasText(tipDto.getIdCardCode())) {
                dto.setQueryType(2);
                List<QueryUndeliveredDrugsXmlRequest.PatientIdentityCardList> patientIdentityCardList = new ArrayList<>();
                QueryUndeliveredDrugsXmlRequest.PatientIdentityCardList patientIdentityCard = new QueryUndeliveredDrugsXmlRequest.PatientIdentityCardList();
                patientIdentityCard.setCardNumber(tipDto.getIdCard());
                patientIdentityCard.setCardType(tipDto.getIdCardCode());
                patientIdentityCardList.add(patientIdentityCard);
                dto.setPatientIdentityCardList(patientIdentityCardList);
            } else {
                if (StringUtils.hasText(tipDto.getMedicalCardID()) && StringUtils.hasText(tipDto.getMedicalCardType())) {
                    dto.setQueryType(3);
                    List<PatientMedicalCardInformation> patientMedicalCardList = new ArrayList<>();
                    PatientMedicalCardInformation patientMedicalCardInformation = new PatientMedicalCardInformation();
                    patientMedicalCardInformation.setPatientMedicalCardNumber(tipDto.getMedicalCardID());
                    patientMedicalCardInformation.setPatientMedicalCardType(tipDto.getMedicalCardType());
                    patientMedicalCardList.add(patientMedicalCardInformation);
                    dto.setPatientMedicalCardList(patientMedicalCardList);
                }
            }
            result = drugTaskingService.queryDrugTakingList(dto);
        } catch (ControllerException e) {
            logger.error("drugTakingTip has error:", e);
            throw new ControllerException("获取患者待取药失败:" + e.getMessage());
        }
        if (CommonUtils.isNotEmpty(result)) {
            vo.setTip(result.size());
        }
        return vo;
    }

    @RpcService
    @Override
    public ClinicGuideTipVO currentRegRecordTip(ClinicGuideTipDTO dto) throws ControllerException {
        Integer tip = 0;
        try {
            List<RecordListBean> recordListBeans = currentRegRecordList(dto.getOrgId(), dto.getMpiId());
            if (CommonUtils.isNotEmpty(recordListBeans)) {
                //是否存在非已预约的数据
                for (RecordListBean record : recordListBeans) {
                    if (!"4".equals(record.getOrderStatus())) {
                        tip++;
                    }
                }
            }
        } catch (ControllerException e) {
            logger.error("查询用户预约挂号记录失败");
        }
        ClinicGuideTipVO vo = new ClinicGuideTipVO();
        vo.setTip(tip);
        return vo;
    }

    /**
     * 查询用户是否正在排队
     *
     * @param dto
     * @return
     */
    @RpcService
    @Override
    public ClinicGuideTipVO queryHospitalQueueTip(ClinicGuideTipDTO dto) {
        Integer tip = 0;
        HospitalFamilyQueueListQo qo = new HospitalFamilyQueueListQo();
        qo.setHospitalCode(dto.getOrgId());
        qo.setMpiId(dto.getMpiId());

        try {
            HospitalFamilyQueueVo vo = queryHospitalQueueList(qo);
            if (CommonUtils.isNotEmpty(vo) && CommonUtils.isNotEmpty(vo.getFamilyQueue())) {
                tip = vo.getFamilyQueue().size();
            }
        } catch (Exception e) {
            logger.error("获取用户排队记录失败", e);
        }
        ClinicGuideTipVO vo = new ClinicGuideTipVO();
        vo.setTip(tip);
        return vo;
    }


    /**
     * 根据mpiId查询排队信息
     */
    @RpcService
    public HospitalFamilyQueueVo queryHospitalQueueList(HospitalFamilyQueueListQo qo) throws Exception {
        String hospitalCode = qo.getHospitalCode();
        String mpiId = qo.getMpiId();
        HospitalFamilyQueueVo rtn = new HospitalFamilyQueueVo();
        //查询出机构信息
        HospitalFamilyQueueListXmlRequest xmlRequest = new HospitalFamilyQueueListXmlRequest();
        Organization organization = organizationInfoService.getOrgDetailByOrgId(hospitalCode);
        if (CommonUtils.isEmpty(organization)) {
            return rtn;
        }
        xmlRequest.setVisitOrganization(organization.getLocalOrgId());
        //根据mpiId查询出用户身份信息
        Certificate certificate = mpiProvider.getCertificate(mpiId);
        if (CommonUtils.isEmpty(certificate)) {
            return rtn;
        }

        List<IdCard> idCardList = new ArrayList<>();
        IdCard idCard = new IdCard();
        idCard.setIdCard(SM4Utils.decryptData_ECB(certificate.getCertificateNo()));
        idCard.setIdCardCode(certificate.getCertificateType());
        idCardList.add(idCard);
        //xml请求
        IdCardLists idCardLists = new IdCardLists();
        idCardLists.setIdCardList(idCardList);
        xmlRequest.setIdCardLists(idCardLists);
        xmlRequest.setQueryType("2");
        xmlRequest.setBusinessType("1");
        //查询his排队信息
        HospitalFamilyQueueListResponse response =
                (HospitalFamilyQueueListResponse) Client.rpcInvoke("hcnInterface.hospitalFamilyQueueList", "queryHospitalFamilyQueueXmlList", xmlRequest);
        //封装参数对象
        List<HospitalFamilyQueueVo.PersonQueue> familyQueues = new ArrayList<>();

        String navigationListSettingForGuideCode = navigationListSettingsService.getNavigationListSettingForGuideCode(organization.getOrgId(), "0101", 1);

        rtn.setFamilyQueue(familyQueues);
        if (CommonUtils.isNotEmpty(response) && CommonUtils.isNotEmpty(response.getPersonQueue())) {
            List<HospitalFamilyQueueListResponse.PersonQueue> personQueue = response.getPersonQueue();
            rtn.setPatientName(personQueue.get(0).getPatientName());
            personQueue.forEach(p -> {
                HospitalFamilyQueueVo.PersonQueue personQueueVo = new HospitalFamilyQueueVo.PersonQueue();
                BeanUtils.copy(p, personQueueVo);
                personQueueVo.setDepartmentLocation(p.getAdmitAddress());
                personQueueVo.setBuildingId(navigationListSettingForGuideCode);
                familyQueues.add(personQueueVo);
            });
        }
        return rtn;

    }

    @RpcService
    public List<RecordListBean> currentRegRecordList(String orgId, String mpiId) throws ControllerException {
        //查询当前用户信息
        try {
            Certificate certificate = mpiProvider.getCertificate(mpiId);
            PatientIdentityVo identityBean = new PatientIdentityVo();
            identityBean.setCardType(certificate.getCertificateType());
            identityBean.setCardNumber(SM4Utils.decryptData_ECB(certificate.getCertificateNo()));
            List<PatientIdentityVo> list = new ArrayList<>();
            list.add(identityBean);
            List<RecordListBean> recordListBeans = regRecordListImpl(orgId, list);
            if (CommonUtils.isEmpty(recordListBeans)) {
                return recordListBeans;
            }
            //根据his订单号查询挂号数据
            List<String> hisOrderNumbers = recordListBeans.stream().map(RecordListBean::getHisOrderNumber).filter(CommonUtils::isNotEmpty).collect(Collectors.toList());
            //
            if (CommonUtils.isEmpty(hisOrderNumbers)) {
                return recordListBeans;
            }
            //挂号数据
            List<OdsRegprepare> regList = regPrepareService.findRegprepareByHisOrderNumberList(hisOrderNumbers);
            if (CommonUtils.isEmpty(regList)) {
                Map<String, Integer> collect = regList.stream().collect(Collectors.toMap(OdsRegprepare::getHisOrderNumber, OdsRegprepare::getId, (o1, o2) -> o1));
                recordListBeans.forEach(r -> {
                    String hisOrderNumber = r.getHisOrderNumber();
                    r.setRegisterId(collect.get(hisOrderNumber));
                });
            }
            return recordListBeans;

        } catch (MPIException e) {
            logger.error("获取用户信息失败", e);
            throw new ControllerException("获取用户信息失败");
        }
    }

    /**
     * 根据病人列表获取预约记录列表
     *
     * @param orgId 机构id
     * @param list  病人身份列表
     */
    @RpcService
    private List<RecordListBean> regRecordListImpl(String orgId, List<PatientIdentityVo> list) throws ControllerException {
        try {
            TakeNumberRequest takeNumberRequest = new TakeNumberRequest();
            takeNumberRequest.setPatientIdentityCardlist(list);
            Organization organization = organizationInfoService.getOrgDetailByOrgId(orgId);
            if (CommonUtils.isEmpty(organization)) {
                throw new ControllerException("机构不能为空");
            }
            if (CommonUtils.isEmpty(organization.getLocalOrgId())) {
                throw new ControllerException("localorgId不能为空");
            }

            takeNumberRequest.setOrganizationId(organization.getLocalOrgId());
            //根据机构配置  获取预约挂号地址
            takeNumberRequest.setRegUrl(organization.getProRegUrl());
            takeNumberRequest.setPatientMedicalCardNumberList(new ArrayList<PatientMedicalVo>());
            takeNumberRequest.setPatientIdlist(new ArrayList<String>());
            List<RecordListBean> result = registrationTransformService.regRecordList(takeNumberRequest);

            List<RecordListBean> recordListBeanList = new ArrayList<>();
            //过滤没有存预约记录的单子
            if (result.size() > 0 && result != null) {
                for (RecordListBean recordListBean : result) {
                    boolean addFlag = true;
                    //默认设置不可取号
                    recordListBean.setPickFlag("0");
                    Date workDate = recordListBean.getWorkDate();
                    if (null != workDate) {
                        //当前时间大于就诊日0点，就可以取号
                        if (System.currentTimeMillis() > workDate.getTime()) {
                            recordListBean.setPickFlag("1");
                        }
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(workDate);
                        calendar.add(Calendar.DAY_OF_MONTH, 1);
                        //问诊日期加一天，若是当前时间大于这个时间，说明这是历史数据，不返回
                        if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
                            addFlag = false;
                        }
                    } else {
                        addFlag = false;
                    }

                    if (addFlag) {
                        OdsRegprepare odsRegprepare = regPrepareService.getRegprepareByHisOrderNumber(recordListBean.getHisOrderNumber());
                        if (CommonUtils.isNotEmpty(odsRegprepare)) {
                            String status = odsRegprepare.getStatus();
                            //2,7,8预约申请成功
                            if (RegStatus.REGSUCCESS.getStatus().equals(status) || RegStatus.REGPAYING.getStatus().equals(status) ||
                                    RegStatus.IS_PAY.getStatus().equals(status)) {
                                recordListBeanList.add(recordListBean);
                            }

                        }
                    }
                }

            }
            return recordListBeanList;
        } catch (ControllerException e) {
            throw new ControllerException(CodeDefinition.REGISTRATION_FAIL, e.getMessage());
        } catch (Throwable e) {
            throw new ControllerException(CodeDefinition.REGISTRATION_FAIL, "签到取号,获取预约记录失败.");
        }
    }

    /**
     * 获取未预约的检查列表
     */
    private List<GetCheckAppointmentItemResponse> check(ClinicGuideCheckDTO dto) throws ControllerException {
        GetCheckAppointmentItemRequest itemRequest = new GetCheckAppointmentItemRequest();

        //机构代码
        itemRequest.setHospitalCode(dto.getOrgCode());
        //患者类型 1.门诊 2.急诊 3 住院 9.其他
        itemRequest.setPatientType(1);
        itemRequest.setPatientIdentityCardType(dto.getIdCardCode());
        itemRequest.setPatientIdentityCardNumber(dto.getIdCard());
        //0未预约  1已预约
        itemRequest.setAppointmentSign(0);
        itemRequest.setEmergency(0);

        //未预约
        List<GetCheckAppointmentItemResponse> list = checkAppointmentService.getCheckAppointmentItem(itemRequest);
        return list;
    }

    /**
     * 获取已预约的检查列表
     */
    private List<GetCheckAppointmentItemResponse> check2(ClinicGuideCheckDTO dto) throws ControllerException {
        GetCheckAppointmentItemRequest itemRequest = new GetCheckAppointmentItemRequest();
        //机构代码
        itemRequest.setHospitalCode(dto.getOrgCode());
        //患者类型 1.门诊 2.急诊 3 住院 9.其他
        itemRequest.setPatientType(1);
        itemRequest.setPatientIdentityCardType(dto.getIdCardCode());
        itemRequest.setPatientIdentityCardNumber(dto.getIdCard());
        //0未预约  1已预约
        itemRequest.setAppointmentSign(1);
        itemRequest.setEmergency(0);

        //已预约
        List<GetCheckAppointmentItemResponse> list = checkAppointmentService.getCheckAppointmentItem(itemRequest);
        List<GetCheckAppointmentItemResponse> data = list;
        //无法确定his接口返回的检查单是否预约的逻辑,这里设置成已预约
        if (CommonUtils.isNotEmpty(data)) {
            data.forEach(d -> d.setAppointmentSign(1));
        }

        return data;
    }

    /**
     * 获取未预约的检验列表
     */
    private ExamAppointListAppResponse exam(ClinicGuideCheckDTO dto) {
        ExamAppointListReq req = new ExamAppointListReq();
        ExamVisitReq visitReq = new ExamVisitReq();
        visitReq.setVisitOrganization(dto.getOrgCode());
        // TODO: 2022/3/10
        visitReq.setQueryType("1");
        visitReq.setMedicalCardType(dto.getMedicalCardType());
        visitReq.setMedicalCardId(dto.getMedicalCardId());
        visitReq.setIdCardCode(dto.getIdCardCode());
        visitReq.setIdCard(dto.getIdCard());

        req.setVisit(visitReq);
        ExamlabReq labRequest = new ExamlabReq();
        labRequest.setIsAppointment("1");
        req.setLabRequest(labRequest);
        BaseResponse<ExamAppointListAppResponse> baseResponse = examineAppointmentService.getExamAppointApp(req);
        return baseResponse.getData();
    }

    /**
     * 获取已预约的检验列表
     */
    private List<ExamAppointmentInfoResp> exam2(ClinicGuideCheckDTO dto) throws ControllerException {
        ExamAppointmentInfoReq req = new ExamAppointmentInfoReq();
        req.setVisitOrganization(dto.getOrgCode());
        req.setMedicalCardType(dto.getMedicalCardType());
        req.setMedicalCardId(dto.getMedicalCardId());
        req.setIdCardCode(dto.getIdCardCode());
        req.setIdCard(dto.getIdCard());

        //未执行
        List<ExamAppointmentInfoResp> list = examineAppointmentService.queryAppointmentInfo(req);
        return list;
    }

}
